import React, { Component, cloneElement } from 'react';
import PropTypes from 'prop-types';

import Orienter from './Orienter';






/* 
Reaction

#props
relative : bool     是否使用相对方向   默认值: true
initOrient ： {lon:number,lat:number} 初始方向
perspective : number    透视点 默认值: 500
maxAngle : number 偏移最大角
scale : 偏移比例    默认值: 1

throttleDelay : number 最短触发时间间隔 默认值: 40
throttleStep : number 最短触发步长 默认值: 1


affectType : "Angle" | "Move" | "Custom"      设置影响类型，当值为Custom时，需要实现getAffectStyle接口
getAffectStyle :(lon,lat)=>ReactStyleObject  获得影响样式的回调函数；



*/



class Reaction extends Component {

    constructor(props) {
        super(props);

        this.orientHandle = this.orientHandle.bind(this);


        this.state = {
            orientation: {
                a: 0,
                b: 0,
                g: 0,
                lon: 0,
                lat: 0,
                dir: 0
            }
        };

        this.updateForProps(props);

        this.thenTime = new Date();


        let orient = new Orienter();
        orient.onOrient = this.orientHandle;
        orient.init();
    }

    componentWillReceiveProps(nextProps) {
        this.updateForProps(nextProps);
    }

    updateForProps(nextProps) {
        let { initOrient } = nextProps;
        if (initOrient) {
            this.initOrient = initOrient;
        }
    }

    orientHandle(orientation) {
        

        let { throttleDelay, throttleStep, relative } = this.props;


        let { b, g,lon } = orientation;
        let { b: pb, g: pg } = this.state.orientation;

        if (lon > 180){
            lon = lon - 360;
            orientation.lon = lon;
        }


        if (!(this.initOrient) && relative) {
            this.initOrient = orientation;
        }


        let db = b - pb;
        let dg = g - pg;


        //节流
        let stepAllow = Math.max(Math.abs(db), Math.abs(dg)) >= throttleStep;

        var now = new Date();
        let delayAllow = now - this.thenTime >= throttleDelay;

        if (stepAllow && delayAllow) {

            this.setState({ orientation });

            this.thenTime = now;
        }


    }

    computeStyle() {

        let { relative, perspective, maxAngle,scale,affectType,getAffectStyle } = this.props;
        let { lon, lat } = this.state.orientation;


        if (relative && this.initOrient) {
            let { lon: itLon, lat: itLat } = this.initOrient;
            lat = lat - itLat;
            lon = lon - itLon;
        }

        lat *= scale;
        lon *= scale;

        if (maxAngle || maxAngle === 0) {
            lat = this.limitAngle(lat, maxAngle);
            lon = this.limitAngle(lon, maxAngle);
        }

        lat = -lat;


        let styleObj = null;

        switch (affectType){
            case "Angle" :{
                let styleStr = `perspective(${perspective}px) rotateX(${lat}deg) rotateY(${lon}deg) rotateZ(0deg)`;
                styleObj = { transform: styleStr };
                break;
            }

            case "Move" :{
                let styleStr = `translate(${lon}px,${lat}px)`;
                styleObj = { transform: styleStr };
                break;
            }

            case "Custom" :{
                styleObj = getAffectStyle(lon,lat);
                break;
            }
        }

        return styleObj;

    }

    limitAngle(angle, maxAngle) {
        let absAngle = Math.abs(angle);
        let limit = angle < 0 ? -maxAngle : maxAngle;
        let final = absAngle < maxAngle ? angle : limit;

        return final;

    }


    render() {
        let myElement = this.props.children;
        let originalStyle = myElement.props.style;
        let tsfStyle = this.computeStyle();
        let style = { ...originalStyle, ...tsfStyle };
        myElement = cloneElement(myElement, { style });
        return myElement;
    }
}



// / Reaction的props的类型说明
Reaction.propTypes = {
    initOrient: PropTypes.shape({
        lon: PropTypes.number,
        lat: PropTypes.number
    }),
    affectType:PropTypes.oneOf(['Angle','Move',"Custom"]),
    getAffectStyle:PropTypes.func,
    relative: PropTypes.bool,
    perspective: PropTypes.number,
    maxAngle: PropTypes.number,
    scale:PropTypes.number,
    //   性能优化
    throttleDelay: PropTypes.number,
    throttleStep: PropTypes.number
};

// Reaction的props的默认值
Reaction.defaultProps = {
    relative: true,
    affectType:"Angle",
    perspective: 500,
    scale:1,
    throttleDelay: 40,
    throttleStep: 1
};


export {Reaction};
export default Reaction;